home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / NI5010.ASM < prev    next >
Assembly Source File  |  1991-01-30  |  22KB  |  881 lines

  1. version    equ    2
  2.  
  3.     include    defs.asm
  4.  
  5. ;Ported from Bill Doster's il.c, a C-language driver for the Interlan NI5010
  6. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  7. ;Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  8.  
  9. ;   Copyright, 1988, 1989, Russell Nelson
  10.  
  11. ;   This program is free software; you can redistribute it and/or modify
  12. ;   it under the terms of the GNU General Public License as published by
  13. ;   the Free Software Foundation, version 1.
  14. ;
  15. ;   This program is distributed in the hope that it will be useful,
  16. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;   GNU General Public License for more details.
  19. ;
  20. ;   You should have received a copy of the GNU General Public License
  21. ;   along with this program; if not, write to the Free Software
  22. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. code    segment    word public
  25.     assume    cs:code, ds:code
  26.  
  27. ; The various IE command registers
  28. EDLC_XSTAT    equ    0        ; EDLC transmit csr
  29. EDLC_XCLR    equ    0        ; EDLC transmit "Clear IRQ"
  30. EDLC_XMASK    equ    1        ; EDLC transmit "IRQ Masks"
  31. EDLC_RSTAT    equ    2        ; EDLC receive csr
  32. EDLC_RCLR    equ    2        ; EDLC receive "Clear IRQ"
  33. EDLC_RMASK    equ    3        ; EDLC receive "IRQ Masks"
  34. EDLC_XMODE    equ    4        ; EDLC transmit Mode
  35. EDLC_RMODE    equ    5        ; EDLC receive Mode
  36. EDLC_RESET    equ    6        ; EDLC RESET register
  37. EDLC_TDR1    equ    7        ; "Time Domain Reflectometry" reg1
  38. EDLC_ADDR    equ    8        ; EDLC station address, 6 bytes
  39.                     ; 0Eh doesn't exist for r/w
  40. EDLC_TDR2    equ    0fh        ; "Time Domain Reflectometry" reg2
  41. IE_GP        equ    10h        ; GP pointer (word register)
  42.                     ; 11h is 2nd byte of GP Pointer
  43. IE_RCNT        equ    10h        ; Count of bytes in rcv'd packet
  44.                     ; 11h is 2nd byte of "Byte Count"
  45. IE_MMODE    equ    12h        ; Memory Mode register
  46. IE_DMA_RST    equ    13h        ; IE DMA Reset.  write only
  47. IE_ISTAT    equ    13h        ; IE Interrupt Status.  read only
  48. IE_RBUF        equ    14h        ; IE Receive Buffer port
  49. IE_XBUF        equ    15h        ; IE Transmit Buffer port
  50. IE_SAPROM    equ    16h        ; window on station addr prom
  51. IE_RESET    equ    17h        ; any write causes Board Reset
  52.  
  53. ; bits in EDLC_XSTAT, interrupt clear on write, status when read
  54. XS_TPOK        equ    80h        ; transmit packet successful
  55. XS_CS        equ    40h        ; carrier sense
  56. XS_RCVD        equ    20h        ; transmitted packet received
  57. XS_SHORT    equ    10h        ; transmission media is shorted
  58. XS_UFLW        equ    08h        ; underflow.  iff failed board
  59. XS_COLL        equ    04h        ; collision occurred
  60. XS_16COLL    equ    02h        ; 16th collision occurred
  61. XS_PERR        equ    01h        ; parity error
  62.  
  63. XS_CLR_UFLW    equ    08h        ; clear underflow
  64. XS_CLR_COLL    equ    04h        ; clear collision
  65. XS_CLR_16COLL    equ    02h        ; clear 16th collision
  66. XS_CLR_PERR    equ    01h        ; clear parity error
  67.  
  68. ; bits in EDLC_XMASK, mask/enable transmit interrupts.  register is r/w
  69. XM_TPOK        equ    80h        ; =1 to enable Xmt Pkt OK interrupts
  70. XM_RCVD        equ    20h        ; =1 to enable Xmt Pkt Rcvd ints
  71. XM_UFLW        equ    08h        ; =1 to enable Xmt Underflow ints
  72. XM_COLL        equ    04h        ; =1 to enable Xmt Collision ints
  73. XM_COLL16    equ    02h        ; =1 to enable Xmt 16th Coll ints
  74. XM_PERR        equ    01h        ; =1 to enable Xmt Parity Error ints
  75.                     ; note: always clear this bit
  76.  
  77. ; bits in EDLC_RSTAT, interrupt clear on write, status when read
  78. RS_PKT_OK    equ    80h        ; received good packet
  79. RS_RST_PKT    equ    10h        ; RESET packet received
  80. RS_RUNT        equ    08h        ; Runt Pkt rcvd.  Len < 64 Bytes
  81. RS_ALIGN    equ    04h        ; Alignment error. not 8 bit aligned
  82. RS_CRC_ERR    equ    02h        ; Bad CRC on rcvd pkt
  83. RS_OFLW        equ    01h        ; overflow for rcv FIFO
  84. RS_VALID_BITS    equ    RS_PKT_OK or RS_RST_PKT or RS_RUNT or RS_ALIGN or RS_CRC_ERR or RS_OFLW
  85.                     ; all valid RSTAT bits
  86.  
  87. RS_CLR_PKT_OK    equ    80h        ; clear rcvd packet interrupt
  88. RS_CLR_RST_PKT    equ    10h        ; clear RESET packet received
  89. RS_CLR_RUNT    equ    08h        ; clear Runt Pckt received
  90. RS_CLR_ALIGN    equ    04h        ; clear Alignment error
  91. RS_CLR_CRC_ERR    equ    02h        ; clear CRC error
  92. RS_CLR_OFLW    equ    01h        ; clear rcv FIFO Overflow
  93.  
  94. ; bits in EDLC_RMASK, mask/enable receive interrupts.  register is r/w
  95. RM_PKT_OK    equ    80h        ; =1 to enable rcvd good packet ints
  96. RM_RST_PKT    equ    10h        ; =1 to enable RESET packet ints
  97. RM_RUNT        equ    08h        ; =1 to enable Runt Pkt rcvd ints
  98. RM_ALIGN    equ    04h        ; =1 to enable Alignment error ints
  99. RM_CRC_ERR    equ    02h        ; =1 to enable Bad CRC error ints
  100. RM_OFLW        equ    01h        ; =1 to enable overflow error ints
  101.  
  102. ; bits in EDLC_RMODE, set Receive Packet mode.  register is r/w
  103. RMD_TEST    equ    80h        ; =1 for Chip testing.  normally 0
  104. RMD_ADD_SIZ    equ    10h        ; =1 5-byte addr match.  normally 0
  105. RMD_EN_RUNT    equ    08h        ; =1 enable runt rcv.  normally 0
  106. RMD_EN_RST    equ    04h        ; =1 to rcv RESET pkt.  normally 0
  107.  
  108. RMD_PROMISC    equ    03h        ; receive *all* packets.  unusual
  109. RMD_MULTICAST    equ    02h        ; receive multicasts too.  unusual
  110. RMD_BROADCAST    equ    01h        ; receive broadcasts & normal. usual
  111. RMD_NO_PACKETS    equ    00h        ; don't receive any packets. unusual
  112.  
  113. ; bits in EDLC_XMODE, set Transmit Packet mode.  register is r/w
  114. XMD_COLL_CNT    equ    0f0h        ; coll's since success.  read-only
  115. XMD_IG_PAR    equ    008h        ; =1 to ignore parity.  ALWAYS set
  116. XMD_T_MODE    equ    004h        ; =1 to power xcvr. ALWAYS set this
  117. XMD_LBC        equ    002h        ; =1 for loopbakc.  normally set
  118. XMD_DIS_C    equ    001h        ; =1 disables contention. normally 0
  119.  
  120. ; bits in EDLC_RESET, write only
  121. RS_RESET    equ    80h        ; =1 to hold EDLC in reset state
  122.  
  123. ; bits in IE_MMODE, write only
  124. MM_EN_DMA    equ    80h        ; =1 begin DMA xfer, Cplt clrs it
  125. MM_EN_RCV    equ    40h        ; =1 allows Pkt rcv.  clr'd by rcv
  126. MM_EN_XMT    equ    20h        ; =1 begin Xmt pkt.  Cplt clrs it
  127. MM_BUS_PAGE    equ    18h        ; =00 ALWAYS.  Used when MUX=1
  128. MM_NET_PAGE    equ    06h        ; =00 ALWAYS.  Used when MUX=0
  129. MM_MUX        equ    01h        ; =1 means Rcv Buff on system bus
  130.                     ; =0 means Xmt Buff on system bus
  131.  
  132. ; bits in IE_ISTAT, read only
  133. IS_TDIAG    equ    80h        ; =1 if Diagnostic problem
  134. IS_EN_RCV    equ    20h        ; =1 until frame is rcv'd cplt
  135. IS_EN_XMT    equ    10h        ; =1 until frame is xmt'd cplt
  136. IS_EN_DMA    equ    08h        ; =1 until DMA is cplt or aborted
  137. IS_DMA_INT    equ    04h        ; =0 iff DMA done interrupt. 
  138. IS_R_INT    equ    02h        ; =0 iff unmasked Rcv interrupt
  139. IS_X_INT    equ    01h        ; =0 iff unmasked Xmt interrupt
  140.  
  141. BFRSIZ        equ    2048    ;number of bytes in a buffer
  142.  
  143.     public    int_no
  144. int_no        db    3,0,0,0        ; interrupt number.
  145. io_addr        dw    0300h,0        ; I/O address for card (jumpers)
  146. ipkt_size    dw    ?
  147. opkt_size    dw    ?
  148.  
  149.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  150. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  151. driver_type    db    3        ;from the packet spec
  152. driver_name    db    'NI5010',0    ;name of the driver.
  153. driver_function    db    2
  154. parameter_list    label    byte
  155.     db    1    ;major rev of packet driver
  156.     db    9    ;minor rev of packet driver
  157.     db    14    ;length of parameter list
  158.     db    EADDR_LEN    ;length of MAC-layer address
  159.     dw    GIANT    ;MTU, including MAC headers
  160.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  161.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  162.     dw    0    ;(# of successive xmits) - 1
  163. int_num    dw    0    ;Interrupt # to hook for post-EOI
  164.             ;processing, 0 == none,
  165.  
  166.     public    rcv_modes
  167. rcv_modes    dw    7        ;number of receive modes in our table.
  168.         dw    0               ;There is no mode zero
  169.         dw    rcv_mode_1
  170.         dw    0        ;don't want to bother.
  171.         dw    rcv_mode_3
  172.         dw    0        ;haven't set up perfect filtering yet.
  173.         dw    rcv_mode_5
  174.         dw    rcv_mode_6
  175.  
  176. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  177. our_type    dw    ?,?
  178. intstat        db    ?
  179.  
  180.     public    as_send_pkt
  181. ; The Asynchronous Transmit Packet routine.
  182. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  183. ;   interrupts possibly enabled.
  184. ; Exit with nc if ok, or else cy if error, dh set to error number.
  185. ;   es:di and interrupt enable flag preserved on exit.
  186. as_send_pkt:
  187.     ret
  188.  
  189.     public    drop_pkt
  190. ; Drop a packet from the queue.
  191. ; Enter with es:di -> iocb.
  192. drop_pkt:
  193.     assume    ds:nothing
  194.     ret
  195.  
  196.     public    xmit
  197. ; Process a transmit interrupt with the least possible latency to achieve
  198. ;   back-to-back packet transmissions.
  199. ; May only use ax and dx.
  200. xmit:
  201.     assume    ds:nothing
  202.     ret
  203.  
  204.  
  205.     public    send_pkt
  206. send_pkt:
  207. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  208. ;  (only if the high-performance bit is set in driver_function)
  209. ;enter with ds:si -> packet, cx = packet length.
  210. ;exit with nc if ok, or else cy if error, dh set to error number.
  211.     assume    ds:nothing
  212.     cmp    cx,RUNT        ; minimum length for Ether
  213.     jae    oklen
  214.     mov    cx,RUNT        ; make sure size at least RUNT
  215. oklen:
  216.     inc    cx            ;round size up to next even number.
  217.     and    cx,not 1
  218.  
  219. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  220. ;only in the transmit mode, hence the initial check.
  221.  
  222.     loadport
  223.     setport    IE_ISTAT
  224.     in    al,dx
  225.     and    al,IS_EN_XMT        ;on-going xmit
  226.     je    send_pkt_2
  227.  
  228.     mov    bx,20000        ;try this many times.
  229. send_pkt_3:
  230.     in    al,dx            ;if not busy, exit.
  231.     and    al,IS_EN_XMT
  232.     je    send_pkt_2
  233.     dec    bx
  234.     jne    send_pkt_3
  235.     mov    dh,CANT_SEND        ;timed out, can't send.
  236.     stc
  237.     ret
  238. send_pkt_2:
  239.  
  240.     pushf            ; No distractions from the receiver
  241.     cli
  242.  
  243. ; Disable the Receiver
  244.     mov    al, 0        ; Mask all Receive Interrupts
  245.     loadport
  246.     setport    EDLC_RMASK
  247.     out    dx,al
  248.  
  249.     mov    al, 0        ; Put Xmt Buffer on System Bus
  250.     setport    IE_MMODE
  251.     out    dx,al
  252.  
  253.     mov    al, 0FFh    ; Clear out any pending Rcv Ints
  254.     setport    EDLC_RCLR
  255.     out    dx,al
  256.  
  257.     mov    ax, BFRSIZ    ; Point GP at beginning of packet
  258.     sub    ax,cx
  259.     setport    IE_GP
  260.     out    dx,ax
  261.  
  262.     setport    IE_XBUF
  263.  
  264.     mov    opkt_size,cx    ; opkt_size = cx;
  265.     cmp    is_186,0    ; Can we use rep outsb?
  266.     je    out86        ; no - have to do it slowly.
  267.     db    0f3h, 06eh    ;masm 4.0 doesn't grok "rep outsb"
  268.     jmp    short ocnteven
  269. out86:
  270.     test    si,1        ; (buf & 1) ?
  271.     jz    obufeven    ; no
  272.     lodsb            ; al = *si++;
  273.     out    dx,al        ; out(dx,al);
  274.     dec    cx        ; cx--;
  275. obufeven:
  276.     mov    di,cx        ; save for later test
  277.     shr    cx,1        ; cx = cnt >> 1; (convert to word count)
  278. ; Do the bulk of the buffer, a word at a time
  279.     jcxz    onobuf        ; if(cx != 0){
  280. xb:    lodsw            ; do { ax = *si++; (si is word pointer)
  281.     out    dx,al        ; out(dx,lowbyte(ax));
  282.     mov    al,ah
  283.     out    dx,al        ; out(dx,hibyte(ax));
  284.     loop    xb        ; } while(--cx != 0); }
  285. ; now check for odd trailing byte
  286. onobuf:    shr    di,1        ; if (di & 1)
  287.     jnc    ocnteven
  288.     lodsb            ;   out(dx,*si++);
  289.     out    dx,al
  290. ocnteven:
  291.  
  292. ; Rewrite where packet starts
  293.     mov    ax,BFRSIZ
  294.     sub    ax,opkt_size
  295.     loadport
  296.     setport    IE_GP
  297.     out    dx,ax
  298.  
  299. ; Flip Xmt Buffer to EDLC Bus so it can be transmitted
  300.     mov    al, MM_MUX
  301.     setport    IE_MMODE
  302.     out    dx,al
  303.  
  304. ; Begin transmission.
  305.     mov    al, MM_EN_XMT or MM_MUX
  306.     setport    IE_MMODE
  307.     out    dx,al
  308.  
  309. ; Cause interrupt after completion (or if something fails)
  310.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  311.     setport    EDLC_XMASK
  312.     out    dx,al
  313.  
  314.     popf
  315.     clc
  316.     ret
  317.  
  318.  
  319.     public    get_address
  320. get_address:
  321. ;get the address of the interface.
  322. ;enter with es:di -> place to get the address, cx = size of address buffer.
  323. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  324.     assume    ds:code
  325.     cmp    cx,EADDR_LEN            ;make sure that we have enough room.
  326.     jb    get_address_2
  327.     cmp    cx,9            ;do we have room for all of it?
  328.     jb    get_address_3        ;no.
  329.     mov    cx,9            ;yes - get the whole thing.
  330.     xor    bx,bx
  331.     jmp    short get_address_1
  332. get_address_3:
  333.     mov    cx,EADDR_LEN
  334.     xor    bx,bx
  335. get_address_1:
  336.     mov    ax,bx
  337.     loadport
  338.     setport    IE_GP
  339.     out    dx,ax
  340.  
  341.     setport    IE_SAPROM
  342.     in    al,dx
  343.     stosb
  344.     inc    bx
  345.     loop    get_address_1
  346.  
  347.     mov    cx,EADDR_LEN
  348.     clc
  349.     ret
  350. get_address_2:
  351.     stc
  352.     ret
  353.  
  354.  
  355. ;Set Ethernet address on controller
  356.     public    set_address
  357. set_address:
  358.     assume    ds:nothing
  359. ;enter with ds:si -> Ethernet address, CX = length of address.
  360. ;exit with nc if okay, or cy, dh=error if any errors.
  361. ;
  362.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  363.     je    set_address_4
  364.     mov    dh,BAD_ADDRESS
  365.     stc
  366.     jmp    short set_address_done
  367. set_address_4:
  368.  
  369.     loadport
  370.     setport    EDLC_ADDR
  371. set_address_1:
  372.     lodsb
  373.     out    dx,al
  374.     inc    dx
  375.     loop    set_address_1
  376. set_address_okay:
  377.     mov    cx,EADDR_LEN        ;return their address length.
  378.     clc
  379. set_address_done:
  380.     push    cs
  381.     pop    ds
  382.     assume    ds:code
  383.     ret
  384.  
  385.  
  386. rcv_mode_1:
  387. ;Set up the receiver interrupts and flush status
  388.     mov    al,RMD_NO_PACKETS
  389.     loadport
  390.     setport    EDLC_RMODE
  391.     out    dx,al
  392.     in    al,dx            ;flush status.
  393.  
  394.     ret
  395.  
  396.  
  397. rcv_mode_3:
  398. ;Set up the receiver interrupts and flush status
  399.     mov    al,RMD_BROADCAST
  400.     loadport
  401.     setport    EDLC_RMODE
  402.     out    dx,al
  403.     in    al,dx            ;flush status.
  404.  
  405.     ret
  406.  
  407.  
  408. rcv_mode_5:
  409. ;Set up the receiver interrupts and flush status
  410.     mov    al,RMD_MULTICAST
  411.     loadport
  412.     setport    EDLC_RMODE
  413.     out    dx,al
  414.     in    al,dx            ;flush status.
  415.  
  416.     ret
  417.  
  418.  
  419. rcv_mode_6:
  420. ;Set up the receiver interrupts and flush status
  421.     mov    al,RMD_PROMISC
  422.     loadport
  423.     setport    EDLC_RMODE
  424.     out    dx,al
  425.     in    al,dx            ;flush status.
  426.  
  427.     ret
  428.  
  429.  
  430.     public    set_multicast_list
  431. set_multicast_list:
  432. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  433. ;return nc if we set all of them, or cy,dh=error if we didn't.
  434.     mov    dh,NO_MULTICAST
  435.     stc
  436.     ret
  437.  
  438.  
  439.     public    terminate
  440. terminate:
  441.     ; put card in held-RESET state
  442.     mov    al,0
  443.     loadport
  444.     setport    IE_MMODE
  445.     out    dx,al
  446.     mov    al,RS_RESET
  447.     loadport
  448.     setport    EDLC_RESET
  449.     out    dx,al
  450.  
  451.     ret
  452.  
  453.  
  454.     public    reset_interface
  455. reset_interface:
  456. ;reset the interface.
  457. ;we don't do anything.
  458.     ret
  459.  
  460.  
  461. ;called when we want to determine what to do with a received packet.
  462. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  463.     extrn    recv_find: near
  464.  
  465. ;called after we have copied the packet into the buffer.
  466. ;enter with ds:si ->the packet, cx = length of the packet.
  467.     extrn    recv_copy: near
  468.  
  469.     extrn    count_in_err: near
  470.     extrn    count_out_err: near
  471.  
  472.     public    recv
  473. recv:
  474. ;called from the recv isr.  All registers have been saved, and ds=cs.
  475. ;Upon exit, the interrupt will be acknowledged.
  476.     assume    ds:code
  477.  
  478.     loadport
  479.     setport    IE_ISTAT
  480.     in    al,dx
  481.     mov    intstat,al
  482.  
  483. ; DMA Complete Interrupt.  We don't use DMA, but just in case ...
  484.     test    al,IS_DMA_INT
  485.     jne    recv_isr_3
  486.  
  487.     mov    al, 0         ; Reset DMA Interrupt
  488.     setport    IE_DMA_RST
  489.     out    dx,al
  490.  
  491. recv_isr_3:
  492.  
  493. ; Transmit Complete/Fail Interrupt
  494.     test    intstat,IS_X_INT
  495.     jne    recv_isr_1
  496.  
  497.     loadport
  498.     setport    EDLC_XSTAT
  499.     in    al,dx
  500.     mov    ah,al
  501.  
  502.     mov    al, 0            ; Disable Xmt IRQ's
  503.     setport    EDLC_XMASK
  504.     out    dx,al
  505.  
  506.     mov    al, 0FFh        ; clr all Xmt IRQ's
  507.     setport    EDLC_XCLR
  508.     out    dx,al
  509.  
  510.     test    ah,XS_COLL
  511.     je    recv_isr_1
  512.     ;Crank counter back to beginning and restart xmt
  513.  
  514.     mov    ax,BFRSIZ        ; Point GP at beginning of packet
  515.     sub    ax,opkt_size
  516.     setport    IE_GP
  517.     out    dx,ax
  518.  
  519.     mov    al, 0        ; De-assert MM_EN_RCV bit Just In Case
  520.     setport    IE_MMODE
  521.     out    dx,al
  522.  
  523.                 ; Flip Xmt Buffer to EDLC Bus and restart xmt
  524.     mov    al, MM_EN_XMT or MM_MUX
  525.     setport    IE_MMODE
  526.     out    dx,al
  527.  
  528.             ; Interrupt for all Transmit errors along with TPOK
  529.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  530.     setport    EDLC_XMASK
  531.     out    dx,al
  532.  
  533.     ret            ; Wait for it to complete again
  534.  
  535. recv_isr_1:
  536.     ; Is this a Receive Packet Interrupt?
  537.     test    intstat,IS_R_INT
  538.     jne    recv_isr_9_j_1        ;no.
  539.  
  540.     loadport
  541.     setport    EDLC_RSTAT        ;get the status of this packet
  542.     in    al,dx
  543.     and    al,RS_VALID_BITS
  544.     cmp    al,RS_PKT_OK        ;is it ok?
  545.     jne    recv_isr_7        ;yes.
  546.  
  547.     ; Clear the interrupt
  548.     mov    al, 0FFh
  549.     loadport
  550.     setport    EDLC_RCLR
  551.     out    dx,al
  552.  
  553.     ; Flip Rcv Buffer onto the system bus
  554.     mov    al, MM_MUX
  555.     setport    IE_MMODE
  556.     out    dx,al
  557.  
  558.     ; Get the size of the packet.
  559.     setport    IE_RCNT
  560.     in    ax,dx
  561.     mov    ipkt_size,ax
  562.  
  563.     cmp    ax,GIANT        ;greater than GIANT?
  564.     jbe    recv_isr_8        ;no.
  565. recv_isr_7:
  566.     call    count_in_err
  567. recv_isr_9_j_1:
  568.     jmp    recv_isr_9
  569. recv_isr_8:
  570. ;Put it on the receive queue
  571.  
  572.     mov    ax,EADDR_LEN+EADDR_LEN            ;seek to the type word.
  573.     setport    IE_GP
  574.     out    dx,ax
  575.  
  576.     setport    IE_RBUF
  577.     in    al,dx            ;read the type word out of the board.
  578.     mov    ah,al
  579.     in    al,dx
  580.     xchg    al,ah            ;should be in network byte order.
  581.     mov    our_type,ax
  582.     in    al,dx            ;read the type word out of the board.
  583.     mov    ah,al
  584.     in    al,dx
  585.     xchg    al,ah            ;should be in network byte order.
  586.     mov    our_type+2,ax
  587.  
  588.     mov    ax,ds            ;look up our type.
  589.     mov    es,ax
  590.     mov    di,offset our_type
  591.     mov    cx,ipkt_size
  592.  
  593.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  594.     mov    ax, es:[di]
  595.     xchg    ah, al
  596.     cmp     ax, 1500
  597.     ja    BlueBookPacket
  598.     inc    di            ;set di to 802.2 header
  599.     inc    di
  600.     mov    dl, IEEE8023
  601. BlueBookPacket:
  602.     call    recv_find
  603.  
  604.     mov    ax,es            ;is this pointer null?
  605.     or    ax,di
  606.     je    recv_isr_9        ;yes - just free the frame.
  607.  
  608.     push    es            ;remember where the buffer pointer is.
  609.     push    di
  610.  
  611.     xor    ax,ax            ;seek to the beginning again.
  612.     loadport
  613.     setport    IE_GP
  614.     out    dx,ax
  615.  
  616.     mov    cx,ipkt_size
  617.     setport    IE_RBUF
  618.  
  619.     cmp    is_186,0    ; Can we use rep insb?
  620.     je    in86        ; no - have to do it slowly.
  621.     db    0f3h, 06ch    ;masm 4.0 doesn't grok "rep insb"
  622.     jmp    short icnteven
  623. in86:
  624. ; If buffer doesn't begin on a word boundary, get the first byte
  625.     test    di,1    ; if(buf & 1){
  626.     jz    ibufeven ;
  627.     in    al,dx    ; al = in(dx);
  628.     stosb        ; *di++ = al
  629.     dec    cx    ; cx--;
  630. ibufeven:
  631.     mov    si,cx    ; size = cx;
  632.     shr    cx,1    ; cx = cnt >> 1; (convert to word count)
  633. ; Do the bulk of the buffer, a word at a time
  634.     jcxz    inobuf    ; if(cx != 0){
  635. rb:    in    al,dx    ; do { al = in(dx);
  636.     mov    ah,al
  637.     in    al,dx    ; ah = in(dx);
  638.     xchg    al,ah
  639.     stosw        ; *si++ = ax; (di is word pointer)
  640.     loop    rb    ; } while(--cx != 0);
  641. ; now check for odd trailing byte
  642. inobuf:    shr    si,1
  643.     jnc    icnteven
  644.     in    al,dx
  645.     stosb        ; *di++ = al
  646. icnteven:
  647.  
  648.     pop    si
  649.     pop    ds
  650.     assume    ds:nothing
  651.     mov    cx,ipkt_size
  652.     call    recv_copy        ;tell them that we copied it.
  653.  
  654.     mov    ax,cs            ;restore our ds.
  655.     mov    ds,ax
  656.     assume    ds:code
  657.  
  658. recv_isr_9:
  659.  
  660. ; Prime Interlan card for another Receive
  661. il_rcv_reset:
  662.  
  663.     ; Rcv packet at start of Boards buffer
  664.     mov    ax,0
  665.     loadport
  666.     setport    IE_GP
  667.     out    dx,ax
  668.  
  669.     ; Clear any remaining Interrupt conditions
  670.     mov    al,0FFh
  671.     setport    EDLC_RCLR
  672.     out    dx,al
  673.  
  674.     ; Set MUX to allow EDLC to access Rcv Buffer
  675.     mov    al,0
  676.     setport    IE_MMODE
  677.     out    dx,al
  678.  
  679. ;
  680. ;    Next section commented out to make promiscous mode work.
  681. ;    It makes no sense to reset the receive mode after each
  682. ;    received packet. M.K.
  683. ;
  684.     ; Enable Receive of Normal and Broadcast Packets only.
  685. ;    mov    al,RMD_BROADCAST
  686. ;    setport    EDLC_RMODE
  687. ;    out    dx,al
  688.  
  689.     ; Enable Receive Interrupts
  690.     mov    al,MM_EN_RCV
  691.     setport    IE_MMODE
  692.     out    dx,al
  693.  
  694.     ; Unmask *all* Receive related interrupts
  695.     mov    al,0FFh
  696.     setport    EDLC_RMASK
  697.     out    dx,al
  698.  
  699.     ret
  700.  
  701.  
  702.     public    recv_exiting
  703. recv_exiting:
  704. ;called from the recv isr after interrupts have been acknowledged.
  705. ;Only ds and ax have been saved.
  706.     assume    ds:nothing
  707.     ret
  708.  
  709.  
  710. end_resident    label    byte
  711.  
  712.     public    usage_msg
  713. usage_msg    db    "usage: NI5010 [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  714.  
  715.     public    copyright_msg
  716. copyright_msg    db    "Packet driver for the Interlan NI5010, version ",'0'+majver,".",'0'+version,CR,LF
  717.         db    "Portions Copyright 1988 Bill Doster",CR,LF,CR,LF
  718.         db    "Promiscous mode fixed by Martin Knoblauch (22-Aug-90).",CR,LF
  719.         db    "Flame <XBR2D96D@DDATHD21.BITNET> for related problems",CR,LF,CR,LF,'$'
  720.  
  721. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  722. no_ni5010_msg    db    "No NI5010 found at that address.",CR,LF,'$'
  723. ether_bdcst    db    EADDR_LEN dup(-1)    ;ethernet broadcast address.
  724. our_address    db    EADDR_LEN+3 dup(?)    ;temporarily hold our address
  725.  
  726. int_no_name    db    "Interrupt number ",'$'
  727. io_addr_name    db    "I/O port ",'$'
  728.  
  729.     extrn    set_recv_isr: near
  730.  
  731. ;enter with si -> argument string, di -> word to store.
  732. ;if there is no number, don't change the number.
  733.     extrn    get_number: near
  734.  
  735. ;enter with dx -> name of word, di -> dword to print.
  736.     extrn    print_number: near
  737.  
  738.     public    parse_args
  739. parse_args:
  740. ;exit with nc if all went well, cy otherwise.
  741.     mov    di,offset int_no
  742.     call    get_number
  743.     mov    di,offset io_addr
  744.     call    get_number
  745.     clc
  746.     ret
  747.  
  748.  
  749. no_ni5010_error:
  750.     mov    dx,offset no_ni5010_msg
  751.     mov    ah,9
  752.     int    21h
  753.     stc
  754.     ret
  755.  
  756.  
  757.     public    etopen
  758. etopen:
  759. ;  Initialize the Ethernet board, set receive type.
  760. ;
  761. ;  check for correct EPROM location
  762. ;
  763.     pushf        ; No distractions from the receiver
  764.     cli
  765.  
  766.     ; Hold up EDLC RESET while the board is configured
  767.     mov    al,RS_RESET
  768.     loadport
  769.     setport    EDLC_RESET
  770.     out    dx,al
  771.  
  772.     ; Hardware reset of Interlan Board
  773.     mov    al,0
  774.     loadport
  775.     setport    IE_RESET
  776.     out    dx,al
  777.  
  778.     call    set_recv_isr
  779.  
  780.     popf        ; Shouldn't be any interrupts from here on out
  781.  
  782.     mov    al,XMD_LBC
  783.     loadport
  784.     setport    EDLC_XMODE
  785.     out    dx,al
  786.  
  787. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  788. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  789.     mov    cl,33
  790.     mov    ax,0ffffh
  791.     shl    ax,cl
  792.     jz    not_186
  793.     mov    is_186,1
  794.     mov    dx,offset using_186_msg
  795.     mov    ah,9
  796.     int    21h
  797. not_186:
  798.  
  799.     push    ds
  800.     pop    es
  801.     mov    di,offset our_address
  802.     mov    cx,EADDR_LEN+3        ;get three extra signature bytes.
  803.     call    get_address
  804.     mov    si,offset our_address
  805.     mov    cx,EADDR_LEN
  806.     call    set_address
  807.  
  808. ;See if there really is a ni5010 there.
  809.     cmp    our_address+EADDR_LEN+0,0
  810.     jne    no_ni5010
  811.     cmp    our_address+EADDR_LEN+1,055h
  812.     jne    no_ni5010
  813.     cmp    our_address+EADDR_LEN+2,0aah
  814.     jne    no_ni5010
  815.  
  816.     mov    cx,EADDR_LEN
  817.     mov    di,offset ether_bdcst
  818.     repe    cmpsb
  819.     jne    have_ni5010        ;not broadcast address -- must be real.
  820. no_ni5010:
  821.     jmp    no_ni5010_error        ;not there -- no ni5010.
  822. have_ni5010:
  823.  
  824.     ; Only enable Transmit-type interrupts while Transmitting
  825.     mov    al,0
  826.     loadport
  827.     setport    EDLC_XMASK
  828.     out    dx,al
  829.  
  830.     ; Establish generic Transmit mode
  831.     mov    al,XMD_IG_PAR or XMD_T_MODE or XMD_LBC
  832.     setport    EDLC_XMODE
  833.     out    dx,al
  834.  
  835.     ; Clear any startup related Transmit interrupts
  836.     mov    al,0FFh
  837.     setport    EDLC_XCLR
  838.     out    dx,al
  839.  
  840.     ; Establish generic Receive mode
  841.     mov    al,RMD_BROADCAST
  842.     setport    EDLC_RMODE
  843.     out    dx,al
  844.  
  845.     ; Reset Rcv State to allow receives
  846.     call    il_rcv_reset
  847.  
  848.     ; Finally un-reset the EDLC
  849.     mov    al,0
  850.     loadport
  851.     setport    EDLC_RESET
  852.     out    dx,al
  853.  
  854.     mov    al, int_no        ; Get board's interrupt vector
  855.     add    al, 8
  856.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  857.     jb    set_int_num        ; No.
  858.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  859. set_int_num:
  860.     xor    ah, ah            ; Clear high byte
  861.     mov    int_num, ax        ; Set parameter_list int num.
  862.  
  863.     mov    dx,offset end_resident
  864.     clc
  865.     ret
  866.  
  867.     public    print_parameters
  868. print_parameters:
  869. ;echo our command-line parameters
  870.     mov    di,offset int_no
  871.     mov    dx,offset int_no_name
  872.     call    print_number
  873.     mov    di,offset io_addr
  874.     mov    dx,offset io_addr_name
  875.     call    print_number
  876.     ret
  877.  
  878. code    ends
  879.  
  880.     end
  881.